import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import _, { clone, get } from 'lodash';
import { Icon } from 'antd';
import './index.less';
import { SERVICE_MAP } from '../../util/sideBar-service';
import { OS_MAP } from '../../util/siderBar_os';

//侧边筛选有子筛选项模块
const subKeysArr = ['location', 'service', 'os'];

let allObject = {};

const ShowMoreList = props => {
  const { items, onSelect, noItemRender } = props;
  const [data, setData] = useState([]);

  //去除名字重复的数组
  const filterData = (name, children) => {
    if (!(children instanceof Array)) {
      return;
    }
    return children.map(item => {
      if (_.get(item.children, []) !== 0) {
        item.children = filterData(item.name, item.children);
      }
      return item;
    });
  };

  /**
   * 构造层级结构
   * @param {object} item 要被构造的数据
   * @param {Array} classify 总层级
   */
  function createNextChildren(item, classify) {
    let currentName = classify[0];
    for (let i = 0; i <= classify.length; i++) {
      let currentObj = _.get(allObject, currentName, false);
      if (i === 0) {
        if (currentObj) {
          let childArr = [..._.get(currentObj, 'arr', [])];
          childArr.push(item.name);
          _.set(allObject, `${currentName}.count`, currentObj.count + item.count);
          _.set(allObject, `${currentName}.arr`, [...childArr]);
        } else {
          allObject[currentName] = {
            name: classify[0],
            count: item.count,
            arr: [item.name],
            children: []
          };
        }
      } else if (i === classify.length) {
        let current = _.get(currentObj, 'children', []);
        current.push({
          name: item.name,
          count: item.count
        });
        _.set(allObject, `${currentName}.children`, [...current]);
      } else if (classify[i] !== 'null') {
        let index = -1;
        _.get(currentObj, 'children', []).filter((item, key) => {
          if (item.name === classify[i]) {
            index = key;
          }
          return item.name === classify[i];
        });

        if (index !== -1) {
          let childArr = [..._.get(currentObj, 'arr', [])];
          childArr.push(item.name);
          currentName = currentName + '.children[' + index + ']';
          _.set(allObject, `${currentName}.count`, currentObj.count + item.count);
          _.set(allObject, `${currentName}.arr`, [...childArr]);
        } else {
          let current = _.get(currentObj, 'children', []);
          let index = current.push({
            name: classify[i],
            count: item.count,
            arr: [item.name],
            children: []
          });
          _.set(allObject, `${currentName}.children`, [...current]);
          currentName = `${currentName}.children` + '[' + (index - 1) + ']';
        }
      }
    }
  }

  function createTree(data, key) {
    if (data.length === 0) {
      return;
    }
    allObject = {};
    for (let i in data) {
      let item = data[i];
      let nameArr = [];
      if (key === 'os') {
        nameArr = _.get(OS_MAP, item.name, '其他|null').split('|');
      } else if (key === 'service') {
        nameArr = _.get(SERVICE_MAP, item.name, '其他').split('|');
      }
      createNextChildren(item, nameArr);
    }

    let newData = [];
    for (let i in allObject) {
      newData.push(allObject[i]);
    }
    allObject = {};
    return newData;
  }

  function dataInit(res) {
    for (let i in res) {
      let children = _.get(res[i], 'children', []);
      if (subKeysArr.includes(res[i].key) && children.length !== 0) {
        res[i].children = children.map(item => {
          item.children = filterData(item.name, item.children);
          item['isTop'] = true;
          return item;
        });
      }
    }
    return res;
  }

  useEffect(() => {
    let result = [...items];
    for (let i in result) {
      if (result[i].key === 'os' || result[i].key === 'service') {
        result[i].children = createTree(result[i].children, result[i].key);
      }
    }
    //做顶部标记
    setData(dataInit([...result]));
  }, [items]);

  const wrapOnSelect = (itemIndex, childIndex, rawValue) => {
    return () => {
      if (typeof onSelect !== 'function') {
        return;
      }
      return onSelect(itemIndex, childIndex, rawValue);
    };
  };

  const [expanedItems, setExpanedItems] = useState(new Array(data.length).fill(false));
  const [closedItems, setClosedItems] = useState(new Array(data.length).fill(false));

  const onExpanChange = (index, value) => {
    const clonedExpanedItems = clone(expanedItems);
    clonedExpanedItems[index] = value;
    setExpanedItems(clonedExpanedItems);
  };

  const triggerClosedItems = index => {
    const clonedClosedItems = clone(closedItems);
    clonedClosedItems[index] = !clonedClosedItems[index];
    setClosedItems(clonedClosedItems);
  };

  const findLenth = (data, name) => {
    if (!(data instanceof Array)) {
      return;
    }
    let len = 0;
    for (let i in data) {
      if (data[i].parent === name) {
        len += 1;
        if (_.get(data[i], 'children', []).length !== 0 && data[i].isExp) {
          len += findLenth(data, data[i].name);
        }
      }
    }
    return len;
  };

  //点击数字展开子筛选项
  const onNumberClick = (itemIndex, itemChildren, childIndex) => {
    let res = [...data];
    let isExp = _.get(res[itemIndex].children[childIndex], 'isExp', false);

    if (isExp) {
      //当前为展开，点击关闭
      res[itemIndex].children[childIndex]['isExp'] = false;
      res[itemIndex].children.splice(
        childIndex + 1,
        findLenth(res[itemIndex].children, res[itemIndex].children[childIndex].name)
      );
    } else {
      //当前为关闭或者
      res[itemIndex].children[childIndex]['isExp'] = true;
      const newChildren = itemChildren.map(item => {
        item.parent = res[itemIndex].children[childIndex].name;
        item.isExp = false;
        return item;
      });
      res[itemIndex].children.splice(childIndex + 1, 0, ...newChildren);
    }
    setData(res);
  };

  return (
    <div className="c-show-more-list">
      {data.map((item, itemIndex) => {
        const {
          title,
          key,
          children: rawChihldren = [],
          limit,
          className,
          itemRender,
          customContent,
          mode = 'single-block', // single-block single-inline double
          closable = true,
          fieldNames
        } = item;

        let children = rawChihldren;

        let content = null;
        let expanElement = null;
        let showLimit = false;
        let selectKey = key || itemIndex;
        let labelName = get(fieldNames, 'label', 'label');
        let valueName = get(fieldNames, 'value', 'value');

        if (customContent) {
          content = <div className="item-customContent">{customContent}</div>;
        } else {
          showLimit = children.length > limit;
          let limitedChildren = children;
          if (limit && !expanedItems[itemIndex]) {
            limitedChildren = limitedChildren.slice(0, limit);
          }
          content = (
            <div className="content">
              {limitedChildren.map((rawChild, childIndex) => {
                if (mode === 'single-block' || mode === 'single-inline') {
                  const label =
                    rawChild instanceof Object ? get(rawChild, labelName, '') : rawChild;
                  return (
                    <p
                      key={childIndex}
                      className={cn('item-child', 'single', { inline: mode === 'single-inline' })}
                      onClick={wrapOnSelect(selectKey, label, rawChild)}
                    >
                      {typeof itemRender === 'function' ? itemRender(rawChild) : label}
                    </p>
                  );
                } else {
                  const label = get(rawChild, labelName, '');
                  const value = get(rawChild, valueName, '');
                  const isTop = get(rawChild, 'isTop', false);
                  return (
                    <p
                      className={cn('item-child', 'double', {
                        black: !isTop && subKeysArr.includes(key)
                      })}
                      key={childIndex}
                      onClick={
                        !subKeysArr.includes(key) && wrapOnSelect(selectKey, label, rawChild)
                      }
                    >
                      {typeof itemRender === 'function'
                        ? itemRender(rawChild)
                        : subKeysArr.includes(key) && _.get(rawChild, 'children', []).length !== 0
                        ? [
                            <span
                              className="label"
                              key="label"
                              onClick={wrapOnSelect(selectKey, label, rawChild)}
                            >
                              {label}
                            </span>,
                            <span
                              className="value"
                              key="value"
                              onClick={() =>
                                onNumberClick(
                                  itemIndex,
                                  _.get(rawChild, 'children', []),
                                  childIndex
                                )
                              }
                            >
                              {value}{' '}
                              <Icon
                                type={_.get(rawChild, 'isExp', false) ? 'caret-down' : 'caret-up'}
                              />
                            </span>
                          ]
                        : [
                            <span
                              className="label"
                              key="label"
                              onClick={
                                subKeysArr.includes(key) && wrapOnSelect(selectKey, label, rawChild)
                              }
                            >
                              {label}
                            </span>,
                            <span className="value" key="value">
                              {value}
                            </span>
                          ]}
                    </p>
                  );
                }
              })}
              {limitedChildren.length === 0 && typeof noItemRender === 'function' && noItemRender()}
            </div>
          );
        }

        expanElement = showLimit ? (
          expanedItems[itemIndex] ? (
            <div
              className={cn('show-more', 'inactive')}
              onClick={() => onExpanChange(itemIndex, false)}
            >
              <span>收起</span>
            </div>
          ) : (
            <div
              className={cn('show-more', 'active')}
              onClick={() => onExpanChange(itemIndex, true)}
            >
              <span>查看更多</span>
            </div>
          )
        ) : null;

        return (
          <div
            className={cn(
              'item',
              className,
              { expan: !closedItems[itemIndex] },
              { close: closedItems[itemIndex] }
            )}
            key={itemIndex}
          >
            <div className="title">
              {title}
              {closable && (
                <Icon
                  className={cn('row')}
                  type="down"
                  onClick={() => triggerClosedItems(itemIndex)}
                />
              )}
            </div>
            {!closedItems[itemIndex] && content}
            {!closedItems[itemIndex] && expanElement}
          </div>
        );
      })}
    </div>
  );
};

ShowMoreList.propTypes = {
  items: PropTypes.arrayOf(
    PropTypes.shape({
      title: PropTypes.string,
      key: PropTypes.string, // 用于选取
      limit: PropTypes.number,
      mode: PropTypes.string,
      children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.object]),
      customContent: PropTypes.element,
      className: PropTypes.string,
      closable: PropTypes.bool,
      itemRender: PropTypes.func,
      fieldNames: PropTypes.object
    })
  ),
  noItemRender: PropTypes.func,
  onSelect: PropTypes.func
};

export default ShowMoreList;
